package com.by.service.impl;

import com.by.bean.Order;
import com.by.bean.OrderDetail;
import com.by.common.utils.Assert;
import com.by.common.utils.GenerateCode;
import com.by.common.utils.RabbitUtils;
import com.by.common.utils.RedisUtils;
import com.by.mapper.GoodsMapper;
import com.by.mapper.OrderDetailMapper;
import com.by.mapper.OrderMapper;
import com.by.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    RedisUtils redisUtils;

    @Autowired
    RabbitUtils rabbitUtils;

    @Autowired
    OrderMapper orderMapper;

    @Autowired
    OrderDetailMapper orderDetailMapper;

    @Autowired
    GoodsMapper goodsMapper;

    @Autowired
    GenerateCode generateCode;

    /**
     * 根据订单编号查询订单
     *
     * @param orderNum
     * @return
     */
    @Override
    public Order getOrder(String orderNum) {
        return orderMapper.getOrder(orderNum);
    }

    @Transactional
    @Override
    public int saveOrder(Order order) {
        if (null == order.getOrderNum()) {
            //说明是普通订单  生成订单编号
            String PREFIX = "PTDD";
            String orderNum = generateCode.generateCode(PREFIX);
        }
        //保存订单
        int rs = orderMapper.save(order);
        Assert.isNotSuccess(rs, "生成订单失败");
        if (null != order.getOrderDetails() && order.getOrderDetails().size() > 0) {
            //保存明细
            rs = orderDetailMapper.batchSave(order.getId(), order.getOrderDetails());
            Assert.isNotSuccess(rs, "订单明细保存失败");

            //更新库存  可以怎么做？ 发送mq消息 到库存队列
            Iterator<OrderDetail> it = order.getOrderDetails().iterator();
            while (it.hasNext()) {
                OrderDetail od = it.next();
                //库存不能减到负数
                rs = goodsMapper.updateStock(od.getGoodsId(), od.getNum());
                Assert.isNotSuccess(rs, "更新库存失败");
            }

        }

        //1分钟未支付  自动取消订单  reids  mq
        rabbitUtils.sendLazy(order.getId() + "", 30 * 1000);
        redisUtils.del("user:id:" + order.getUserId());
        return 1;
    }

    /**
     * 更新订单状态
     *
     * @param id
     * @return
     */
    @Override
    public int updateStatus(int id) {
        return orderMapper.updateStatus(id);
    }

    @Override
    public String save(int userId, int goodsId) {

        String userKey = "user:id:" + userId;
        //判断用户是否抢购过
        boolean flag = redisUtils.setNx(userKey, goodsId + "");
        if (!flag) {
            //说明抢过了
            return redisUtils.get(userKey);
        }

        String key = "goods:id:" + goodsId;
        //尝试扣减库存
        List<String> keys = new ArrayList<>();
        keys.add(key);
        Long stock = redisUtils.eval(getLua(), keys);
        if (stock == 0) {
            System.out.println(userId + "抢购失败:" + stock);
            return null;//抢购失败
        }

        System.out.println("用户" + userId + "抢购第" + stock + "台成功");


        //获取秒杀订单编号
        String PREFIX = "MSDD";
        String orderNum = generateCode.generateCode(PREFIX);
        //记录当前用户抢购成功
        redisUtils.set(userKey, orderNum);

        //将用户id和商品id发送到mq里
        rabbitUtils.send(userId + "@" + goodsId + "@" + orderNum);

        return orderNum;//返回抢购成功
    }


    /**
     * @return -1 代表没有库存  如果有 代表扣减后的库存
     */
    String getLua() {
        StringBuilder lua = new StringBuilder();
        lua.append("    local stock = tonumber(redis.call('get', KEYS[1]));");
        lua.append("    if (stock == 0) then");
        lua.append("        return 0;");
        lua.append("    end;");
        lua.append("    if (stock > 0) then");
        lua.append("        redis.call('decr', KEYS[1]);");
        lua.append("        return stock;");
        lua.append("    end;");
        return lua.toString();
    }


}